package hotnet.nio;

import java.io.IOException;
import java.net.SocketException;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;

import hotnet.config.AbstractIoSocketSessionConfig;
import hotnet.handler.IoHandler;
import hotnet.processor.IoProcessor;
import hotnet.service.IoService;
import hotnet.session.AbstractIoSession;

public class NioSocketSession extends AbstractIoSession {
    protected final SocketChannel channel;
    protected SelectionKey key;
	
	public NioSocketSession(IoProcessor processor, SocketChannel channel, IoService service) {
		super(processor, service);
		
		this.channel = channel;
		this.config = new SocketSessionConfigImp();
		this.config.setAll(service.getDefaultSessionConfig());
	}
	
	public SelectionKey getSelectionKey() {
        return key;
    }
	
	public void setSelectionKey(SelectionKey key) {
        this.key = key;
    }
	
	@Override
	public SocketChannel getChannel() {
		return channel;
	}
	
	/* real config set imp */
	private class SocketSessionConfigImp extends AbstractIoSocketSessionConfig {
		@Override
		public boolean isReuseAddress() {
			try {
				return channel.socket().getReuseAddress();
			} catch(SocketException e) {
				throw new RuntimeException(e);
			}
		}

		@Override
		public void setReuseAddress(boolean reuseAddress) {
			try {
				channel.socket().setReuseAddress(reuseAddress);
			} catch(SocketException e) {
				throw new RuntimeException(e);
			}
		}

		@Override
		public int getReceiveBufferSize() {
			try {
				return channel.socket().getReceiveBufferSize();
			} catch(SocketException e) {
				throw new RuntimeException(e);
			}
		}

		@Override
		public void setReceiveBufferSize(int receiveBufferSize) {
			try {
				channel.socket().setReceiveBufferSize(receiveBufferSize);
			} catch(SocketException e) {
				throw new RuntimeException(e);
			}
		}

		@Override
		public int getSendBufferSize() {
			try {
				return channel.socket().getSendBufferSize();
			} catch(SocketException e) {
				throw new RuntimeException(e);
			}
		}

		@Override
		public void setSendBufferSize(int sendBufferSize) {
			try {
				channel.socket().setReceiveBufferSize(sendBufferSize);
			} catch(SocketException e) {
				throw new RuntimeException(e);
			}
		}

		@Override
		public boolean isKeepAlive() {
			try {
				return channel.socket().getKeepAlive();
			} catch(SocketException e) {
				throw new RuntimeException(e);
			}
		}

		@Override
		public void setKeepAlive(boolean keepAlive) {
			try {
				channel.socket().setKeepAlive(keepAlive);
			} catch(SocketException e) {
				throw new RuntimeException(e);
			}
		}

		@Override
		public int getSoLinger() {
			try {
				return channel.socket().getSoLinger();
			} catch(SocketException e) {
				throw new RuntimeException(e);
			}
		}

		@Override
		public void setSoLinger(int soLinger) {
			try {
				if (soLinger <= 0)
					channel.socket().setSoLinger(false, 0);
				else {
					channel.socket().setSoLinger(true, soLinger);
				}
			} catch(SocketException e) {
				throw new RuntimeException(e);
			}
		}

		@Override
		public boolean isTcpNoDelay() {
			try {
				return channel.socket().getTcpNoDelay();
			} catch(SocketException e) {
				throw new RuntimeException(e);
			}
			
		}

		@Override
		public void setTcpNoDelay(boolean tcpNoDelay) {
			try {
				channel.socket().setTcpNoDelay(tcpNoDelay);
			} catch(SocketException e) {
				throw new RuntimeException(e);
			}
		}

		@Override
		public boolean isBlocking() {
			return channel.isBlocking();
		}

		@Override
		public void setBlocking(boolean blocking) {
			try {
				channel.configureBlocking(blocking);
			} catch(IOException e) {
				throw new RuntimeException(e);
			}
			
		}
		
	}
	
}
